package com.cloudptt.api.product.func.sys.fsm;

import android.content.Context;

import com.cloudptt.api.comm.CauseCont;
import com.cloudptt.api.comm.CommDlg;
import com.cloudptt.api.models.ErrInfo;
import com.cloudptt.api.product.ISysOperator;
import com.cloudptt.api.product.func.IFunc;
import com.cloudptt.api.product.func.call.CallAttr;
import com.cloudptt.api.product.func.sys.SysFunc;
import com.cloudptt.api.product.func.sys.SysStateInfo;
import com.cloudptt.api.product.func.sys.listener.ProfileListener;
import com.cloudptt.api.product.func.sys.listener.SysListener;
import com.cloudptt.api.product.log.Log;
import com.cloudptt.api.product.operator.SysOperator;
import com.cloudptt.api.product.res.Resource;
import com.mcptt.config.ConfigCenter;
import com.mcptt.config.ConfigListener;
import com.mcptt.config.callback.IAuthCallback;
import com.mcptt.config.local.SysConfig;
import com.mcptt.config.model.McIdInfo;
import com.mcptt.config.ue.initial.UeInitProfile;
import com.mcptt.http.auth.process.HttpAuthFailedException;
import com.mcptt.http.auth.process.result.FinalResult;

public class SysAgent implements ISysState,ISysOperator, ConfigListener, IAuthCallback {


	private Context ctx = null;
	private SysOperator operator = null;
	private SysConfig config = null;

	private ISysState curSysState = null;
	private SysStateInfo curStateInfo = null;

	private SysListener sysListener = null;
	private ProfileListener profileListener = null;
	//	private SysAddrListener sysAddrListener = null;

	private IFunc superFunc = null;
	private boolean networkDisconnect = false;
	private ConfigCenter configCenter = null;
	private boolean isRefresh = false;
	private int publishResult = 0;
	private int publishCount = 0;
//	private SysBroadcast broadcast = null;


	public SysAgent(Context ctx, SysConfig config, SysOperator operator, IFunc superFunc, ConfigCenter configCenter)
	{
		this.ctx = ctx;
		this.config = config;
		this.operator = operator;
		//		this.sysAddrListener = addrListener;
		this.curSysState = new SvrStopState(this);
		this.superFunc = superFunc;
		this.configCenter = configCenter;
		this.isRefresh = false;
	}

	public void goToState(int nextState,int cause)
	{
		Log.d(SysFunc.Log_Key, "goToState:["+ SysStateInfo.stateTag(this.curSysState.getState()) + " to "+ SysStateInfo.stateTag(nextState) + "] cause = " + cause);
		ISysState state = null;
		switch (nextState)
		{
			case SysStateInfo.SysState_SvrStopState:
				state = new SvrStopState(this);
				break;
			case SysStateInfo.SysState_SvrStartState:
				this.isRefresh = false;
				state = new SvrStartState(this);
				Log.e(SysFunc.Log_Key, "goToState setCurState SvrStartState");
				break;
			case SysStateInfo.SysState_HttpGetingState:
				state = new HttpGetingState(ctx,this);
				break;
			case SysStateInfo.SysState_HttpGetSucState:
				state = new HttpGetSucState(this);
				break;
			case SysStateInfo.SysState_HttpAuthingState:
				state = new HttpAuthingState(ctx,this);
				break;
			case SysStateInfo.SysState_HttpAuthSucState:
				state = new HttpAuthSucState(this);
				break;
			case SysStateInfo.SysState_HttpRefreshingState:
				state = new HttpRefreshingState(ctx,this);
				break;
			case SysStateInfo.SysState_SipAuthingState:
				state = new SipAuthingState(ctx,this);
				break;
			case SysStateInfo.SysState_SipAuthSucState:
				state = new SipAuthSucState(this);
				break;
			case SysStateInfo.SysState_SipPulishingState:
				state = new SipPublishingState(ctx,this);
				break;
			case SysStateInfo.SysState_SipPulishSucState:
				long expires = config.getExpireData();
				state = new SipPublishSucState(ctx,this,expires,isRefresh);
				this.isRefresh = true;
				break;
			default:
				Log.e(SysFunc.Log_Key, "Illegal state="+ nextState);
				return;//!!!
		}
		this.setCurState(state,cause);
	}
	public void setSysListener(SysListener sysListener)
	{
		this.sysListener = sysListener;
	}
	public void setProfileListener(ProfileListener profileListener)
	{
		this.profileListener = profileListener;
	}

	public SysStateInfo getSysStateInfo()
	{
		Log.debug(this.getClass(), "getSysStateInfo curStateInfo = " + curStateInfo);
		return curStateInfo;
	}

	public int getPublishResult() {
		return publishResult;
	}

	private void setCurState(ISysState sysState,int cause)
	{
		Log.e(SysFunc.Log_Key, "setCurState sysState = " + SysStateInfo.stateTag(sysState.getState()) + " cause = " + SysStateInfo.causeTag(cause));
		this.curSysState.destory();
		this.curSysState = sysState;
		int state = curSysState.getState();

		boolean isInputedUser = config.getMcpttLoginInfo().isInputedUser();
		boolean isInvalidUser = config.getMcpttLoginInfo().isInvalidUser();
		Log.e(SysFunc.Log_Key, "setCurState isInputedUser = "+ isInputedUser + " isInvalidUser = "+ isInvalidUser + " McpttLoginInfo = " + config.getMcpttLoginInfo());
		if(state ==  SysStateInfo.SysState_SvrStartState)
		{
			if(cause == SysStateInfo.Cause_Password
				|| cause == SysStateInfo.Cause_RefreshErr)
			{
				config.getMcpttLoginInfo().clearMcpttLoginInfo();
			}
			if(isInvalidUser)
			{
				cause = SysStateInfo.Cause_Logout;
			}
		}
		curStateInfo = new SysStateInfo(state,cause);
		if(sysListener != null)
		{
			sysListener.onSysState(curStateInfo);
		}
		else
		{
			Log.e(SysFunc.Log_Key, "setCurState sysListener = null");
		}
		if(!isInputedUser
			&& (state ==  SysStateInfo.SysState_SvrStartState || state == SysStateInfo.SysState_HttpGetSucState || state == SysStateInfo.SysState_HttpAuthSucState))
		{
			doNextActionBySysState(state, cause);
		}
		else if(!isInvalidUser
			&& state ==  SysStateInfo.SysState_SipAuthSucState) {
			doNextActionBySysState(state, cause);
		}

		if(cause == SysStateInfo.Cause_RefreshErr
			&& state ==  SysStateInfo.SysState_SvrStartState)
		{
			doForceDetach();
		}
	}

	private void doNextActionBySysState(int state,int cause)
	{
		Log.d(SysFunc.Log_Key, "doNextActionBySysState state = " +  SysStateInfo.stateTag(state) + " cause = " +  SysStateInfo.causeTag(cause));
		if(cause != SysStateInfo.Cause_Suc)
		{
			return;
		}
		if(state == SysStateInfo.SysState_SvrStartState)
		{
			Log.d(SysFunc.Log_Key, "doNextActionBySysState cause = " +  SysStateInfo.causeTag(cause));
			if(cause == SysStateInfo.Cause_Suc) {
				doSysAction(SysConst.SysAction_HttpGet);
			}
		}
		else if(state == SysStateInfo.SysState_HttpGetSucState)
		{
			doSysAction(SysConst.SysAction_HttpAuth);
		}
		else if(state == SysStateInfo.SysState_HttpAuthSucState)
		{
			doSysAction(SysConst.SysAction_SipAuth);
		}
		else if(state == SysStateInfo.SysState_SipAuthSucState
				&& cause != SysStateInfo.Cause_Failed)
		{
			doSysAction(SysConst.SysAction_Publish);
		}
	}

	public void doSipAuth()
	{
		Log.d(SysFunc.Log_Key, "doSipAuth");
		operator.login();
	}
	public void doHttpGet()
	{
		Log.d(SysFunc.Log_Key, "doHttpGet");
//		operator.httpGet(this);
		this.configCenter.initMcpttConfig(this);
	}

//	public void doGetUserProfile(int mcType)
//	{
//		Log.d(SysFunc.Log_Key, "doGetUserProfile");
//		this.configCenter.getUserProfile(mcType,this);
//	}

	public void doHttpAuth()
	{
		Log.d(SysFunc.Log_Key, "doHttpAuth");
//		operator.httpAuth(this);
		McIdInfo idInfo = config.getMcpttLoginInfo().getMcIdInfo();//teke
		String mcId = idInfo.getAddrId();//.getMcId();//mcs
//		String mcId = config.getMcpttLoginInfo().getImsInfo().getImpu();////SERVER DIFFERENT
		String pwd = idInfo.getPwd();
		configCenter.httpAuth(mcId, pwd, this);
	}
	public void doHttpRefresh()
	{
		Log.d(SysFunc.Log_Key, "doHttpRefresh");
		String refreshToken = config.getRefreshToken();
		configCenter.doHttpRefreshToken(refreshToken);
	}
	public void doSipUnAuth()
	{
		Log.d(SysFunc.Log_Key, "doSipUnAuth");
		operator.logout();
	}

	public void doPublishPocSetting()
	{
		Log.d(SysFunc.Log_Key, "doPublishPocSetting");
		publishCount = 0;
		McIdInfo idInfo = config.getMcpttLoginInfo().getMcIdInfo();//teke
		String accessToken = idInfo.getAccessToken();
		operator.sendPublishPocSetting(CallAttr.McType_McPtt,accessToken);
		operator.sendPublishPocSetting(CallAttr.McType_McVideo,accessToken);
		operator.sendPublishPocSetting(CallAttr.McType_McData,accessToken);
	}
	public void doSubcribeCms(int mcType)
	{
		Log.d(SysFunc.Log_Key, "doSubcribeCms mcType = " + mcType);
		McIdInfo idInfo = config.getMcpttLoginInfo().getMcIdInfo();//teke
		String accessToken = idInfo.getAccessToken();
		operator.subcribeCms(mcType,accessToken);
	}

	@Override
	public int doSysAction(int sysAction) {
		Log.d(SysFunc.Log_Key,"doSysAction curSysState =  " + SysStateInfo.stateTag(this.curSysState.getState())  + " sysAction = " + SysConst.sysActionTag(sysAction));
		// TODO Auto-generated method stub
		return curSysState.doSysAction(sysAction);
	}

	@Override
	public void recevSysMsg(int sysMsgId) {
		// TODO Auto-generated method stub
		Log.d(SysFunc.Log_Key,"recevSysMsg curSysState =  " + SysStateInfo.stateTag(this.curSysState.getState())  +  " sysMsgId = " +SysConst.sysMsgTag(sysMsgId));
		curSysState.recevSysMsg(sysMsgId);
		if(sysMsgId == SysConst.SysMsg_Sip_Auth_Failed
				|| sysMsgId == SysConst.SysMsg_Sip_Auth_Timeout)
		{
			String str = Resource.getString("login_failed");
			CommDlg.showShortToast(ctx, str);
		}
		if(sysMsgId == SysConst.SysMsg_Http_Get_Suc)
		{
//			curStateInfo = new SysStateInfo(state,cause);
//			sysListener.onSysState(SysConst.SysAction_Download_UeInitProfile);
//			this.configCenter.initMcpttConfig(this);
		}
	}
	@Override
	public void recevHttpResult(boolean result,int code)
	{
		Log.d(SysFunc.Log_Key,"recevHttpResult curSysState =  " + SysStateInfo.stateTag(this.curSysState.getState())  +  " result = " +result  +  " code = " +code);
	}
	@Override
	public int recevPublishResult(int mcType,int publishCount,boolean isSuc)
	{
		Log.d(SysFunc.Log_Key,"recevPublishResult curSysState =  " + SysStateInfo.stateTag(this.curSysState.getState())  +  " mcType = " +mcType +  " publishCount = " +publishCount +  " isSuc = " +isSuc);
		return curSysState.recevPublishResult(mcType,publishCount,isSuc);
	}

	@Override
	public int getState() {
		// TODO Auto-generated method stub
		return curSysState.getState();
	}


	public void logout() {
		// TODO Auto-generated method stub
		if(config != null)
		{
			config.getMcpttLoginInfo().clearMcpttLoginInfo();
		}
//		this.recevSysMsg(SysConst.SysMsg_Logout);
		doSysAction(SysConst.SysAction_Logout);
		//		this.doSipUnAuth();
//		this.curSysState = new SvrStartState(this);
//		goToState(SysStateInfo.SysState_SvrStartState,SysStateInfo.Cause_Logout);
	}

	@Override
	public void destory() {
		// TODO Auto-generated method stub
		this.curSysState.destory();
	}

	public void onSipRegResult(int code,String name,String num)
	{
		Log.d(SysFunc.Log_Key, "onSipRegResult code = " +code + " name = " + name + " num = " + num);
		if (code/100 != 2)
		{
			ErrInfo errInfo = new ErrInfo(CauseCont.ERROR_TITLE_SIP,code);
//			String errStr = ErrInfo.getErrDesc(ctx,ErrInfo.Title_pttcallreq,code);
			CommDlg.showToast(ctx, errInfo.getErrDesc());
			//this.doSipUnAuth();
			if(code == 408)
			{
				recevSysMsg(SysConst.SysMsg_Sip_Auth_Timeout);
			}
			else
			{
				recevSysMsg(SysConst.SysMsg_Sip_Auth_Failed);
			}
			if(superFunc != null)
			{
				superFunc.onLogined(config.getMcInfo(),config.getBootStrapSvr(),false);
			}
		}
		else
		{
			if(networkDisconnect)
			{
				if(sysListener != null) {
					this.sysListener.onSysState(curStateInfo);
				}
				networkDisconnect = false;
			}

			Log.d(SysFunc.Log_Key, "onSipRegResult this.config.isLogined() = " + this.config.isLogined());
			if(!this.config.isLogined())
			{
				this.config.setLoginedTrue();
				this.config.setUserInfoAfterLoginSuc(name,num);
			}
			recevSysMsg(SysConst.SysMsg_Sip_Auth_Suc);
			this.doKeepAlive(true);
			if(superFunc != null)
			{
				superFunc.onLogined(config.getMcInfo(),config.getBootStrapSvr(),true);
			}
		}
	}

	public void onSipUnRegResult(int code,String num)
	{
		Log.d(SysFunc.Log_Key, "onSipUnRegResult code = " +code  + " num = " + num);
//		if (code/100 == 2)
		{
			recevSysMsg(SysConst.SysMsg_Logout_Suc);
//			if(superFunc != null)
//			{
//				superFunc.onLogined(config.getMcInfo(),config.getBootStrapSvr(),false);
//			}
		}
	}

	public void onPublishResult(int code,int mcType) {
		Log.d(SysFunc.Log_Key, "onPublishResult code = " + code + " mcType = " + mcType + " publishResult = " + publishResult);
		boolean isSuc = false;
		publishCount = publishCount | mcType;
		if(code/100 == 2) {
			isSuc = true;
			publishResult = publishResult | mcType;
			Log.d(SysFunc.Log_Key, "onPublishResult true publishRsult = " + publishResult + " mcType = " + mcType);
		}
		else
		{
			if((publishResult & mcType) != 0)
			{
				publishResult = publishResult - mcType;
			}
			Log.d(SysFunc.Log_Key, "onPublishResult false publishRsult = " + publishResult + " mcType = " + mcType);
		}
		Log.d(SysFunc.Log_Key, "onPublishResult isSuc = " + isSuc + " publishRsult = " + publishResult + " publishCount = " + publishCount);
		recevPublishResult(mcType,publishCount,isSuc);
		if(config != null)
		{
			config.getMcInfo().setPublishRsult(publishResult);
		}

//		if	(mcType == CallAttr.McType_McPtt)
//		{
//			this.operator.sendPublishPocSetting(CallAttr.McType_McVideo);
//		}
//		else if	(mcType == CallAttr.McType_McVideo)
//		{
//			this.operator.sendPublishPocSetting(CallAttr.McType_McData);
//
//		}
//		else if	(mcType == CallAttr.McType_McData)
//		{
//			Log.d(SysFunc.Log_Key, "onPublishResult send mcType = " + mcType);
////			this.operator.subcribeCms(CallAttr.McType_McPtt);
//		}
		superFunc.onPublishResult(publishResult);
	}



	public void onSubscribeResult(int code,int mcType) {
		Log.d(SysFunc.Log_Key, "onSubscribeResult code = " + code + " mcType = " + mcType);
		boolean isSuc = false;
		if(code/100 == 2) {
			isSuc = true;
		}
		Log.d(SysFunc.Log_Key, "onSubscribeResult isSuc = " + isSuc);
//		if	(mcType == CallAttr.McType_McPtt)
//		{
//			this.operator.subcribeCmsGms(CallAttr.McType_McVideo);
//		}
//		else if	(mcType == CallAttr.McType_McVideo)
//		{
//			this.operator.subcribeCmsGms(CallAttr.McType_McData);
//
//		}
//		else if	(mcType == CallAttr.McType_McData)
//		{
//		}
		superFunc.onSubscribeCmsGmsResult(isSuc,mcType);
	}

	public void doForceDetach()
	{
		Log.d(SysFunc.Log_Key, "doForceDetach");
		if(this.sysListener != null)
		{
			this.sysListener.onForceDetach();
		}
		else
		{
			Log.d(SysFunc.Log_Key, "sysListener = null");
		}
	}

	public void doSvrRestart()
	{
		Log.d(SysFunc.Log_Key, "doSvrRestart");
		if(this.sysListener != null)
		{
			this.sysListener.onSvrRestart();
		}
		else
		{
			Log.d(SysFunc.Log_Key, "sysListener = null");
		}
	}
	public void doKeepAlive(boolean isconnected)
	{
		Log.d(SysFunc.Log_Key, "doKeepAlive isconnected = " + isconnected);
		if(this.sysListener != null)
		{
			this.sysListener.onKeepAlive(isconnected);
		}
		else
		{
			Log.d(SysFunc.Log_Key, "sysListener = null");
		}
	}
	//	}

//	@Override
//	public void onOpResult(int id, boolean isSuc, SessionInfo info,int cause, String str) {
//		// TODO Auto-generated method stub
//		Log.d(SysFunc.Log_Key, "onOpResult id = " + id + "onOpResult isSuc = " + isSuc);
//		if(id == IHttpOpCb.Id_Get)
//		{
//			if(isSuc)
//			{
//				this.recevSysMsg(SysConst.SysMsg_Http_Get_Suc);
//			}
//			else
//			{
//				this.recevSysMsg(SysConst.SysMsg_Http_Get_Failed);
//			}
//		}
//		else if(id == IHttpOpCb.Id_Auth)
//		{
//			if(isSuc)
//			{
//				this.recevSysMsg(SysConst.SysMsg_Http_Auth_Suc);
//			}
//			else
//			{
//				this.recevSysMsg(SysConst.SysMsg_Http_Auth_Failed);
//				ErrInfo errInfo = new ErrInfo(CauseCont.Title_HttpAuth,cause);
//				if( errInfo != null )
//				{
//					String errStr = errInfo.getErrDesc();
//					CommDlg.show(ctx, errStr);
//				}
//			}
//		}
//	}

	public void setNetworkDisconnect(boolean networkDisconnect) {
		this.networkDisconnect = networkDisconnect;
	}

	@Override
	public void initConfigSuc(String fileName) {
		Log.d(SysFunc.Log_Key, "initConfigSuc fileName = " + fileName);
		if(fileName == null)
		{
			return;
		}
		if(UeInitProfile.FileName.equals(fileName)) {
			recevSysMsg(SysConst.SysMsg_Http_Get_Suc);
		}
		if(profileListener != null)
		{
			profileListener.initConfigSuc(fileName);
		}
//		else if(UserProfile.FileName_Mcptt.equals(fileName))
//		{
//			List<GroupInfo> list = dbAdapter.getGroupInfoList();
//			if(list != null
//				&& list.size() > 0) {
//				String[] groupIdArray = new String[list.size()];
//				int i = 0;
//				for (Iterator<GroupInfo> iterator = list.iterator();iterator.hasNext();)
//				{
//					GroupInfo info = iterator.next();
//					groupIdArray[i] = info.getGroupId();
//				}
//				operator.subcribeGms(groupIdArray);
//			}
//		}
	}

	@Override
	public void initConfigFailed(String fileName, String errStr) {
		Log.e(SysFunc.Log_Key, "initConfigFailed fileName = " + fileName + " errStr = " + errStr);
		if(fileName != null
				&& UeInitProfile.FileName.equals(fileName))
		{
			recevSysMsg(SysConst.SysMsg_Http_Get_Failed);
			String str = Resource.getString("srv_status_dscp_13");
			CommDlg.showToast(ctx,str);
		}
		if(profileListener != null)
		{
			profileListener.initConfigFailed(fileName,errStr);
		}
	}

	@Override
	public void httpAuthSuc(int id,FinalResult finalResult) {
		Log.d(SysFunc.Log_Key,"httpAuthSuc curSysState =  " + SysStateInfo.stateTag(this.curSysState.getState())   +  " id = " +id +  " finalResult = " +finalResult);
		if(curSysState != null)
		{
			curSysState.recevHttpResult(true, HttpAuthFailedException.Code_Suc);
		}
//		doGetUserProfile(CallAttr.McType_McPtt);
	}

	@Override
	public void httpAuthFailed(int id,int code,String errStr) {
		Log.d(SysFunc.Log_Key,"httpAuthFailed curSysState =  " + SysStateInfo.stateTag(this.curSysState.getState())  +  " id = " +id +  " errStr = " +errStr);

//		String str = Resource.getString("login_failed");
//		CommDlg.showToast(ctx,str + " " + errStr);
		if(curSysState != null)
		{
			curSysState.recevHttpResult(false,code);
		}
	}


//	private void recvNotifyFromQueue()
//	{
//		Log.e(SysFunc.Log_Key, "recvNotifyFromQueue isDownloadGroup = " + this.config.isDownloadGroup());
//		String xmlStr = this.downloadQueue.poll();
//		Log.e(SysFunc.Log_Key, "recvNotifyFromQueue xmlStr = " + xmlStr);
//		if(xmlStr != null)
//		{
//			String cmsUrl = config.getBootStrapSvr().toCmsHttpUrl();
//			String gmsUrl = config.getBootStrapSvr().toGmsHttpUrl();
//			configCenter.recvNotify(cmsUrl,gmsUrl,xmlStr, this);
//		}
//		if(!this.config.isDownloadGroup()
//				&& this.downloadQueue.size() <= 0)
//		{
//			this.config.setDownloadGroupTrue();
//			SystemClock.sleep(1000);
//			pushGroupRecvNotify();
//		}
//	}
//
//	private void pushUserProfileNotifyStr(int type,String id)
//	{
//		String xmlStr = XcapParser.getUeInitProfileXcapDoc(type,id);
//		boolean isOk = downloadQueue.offer(xmlStr);
//		Log.d(SysFunc.Log_Key, "pushUserProfileNotifyStr isOk = " + isOk + " downloadQueue.size() = " + downloadQueue.size());
//	}
//	private void pushGroupRecvNotifyStr(int type,String groupid)
//	{
//		Log.d(SysFunc.Log_Key, "pushGroupRecvNotifyStr type = " + type + " groupid = " + groupid);
//		String xmlStr = XcapParser.getGroupXcapDoc(type,groupid);
//		boolean isOk = downloadQueue.offer(xmlStr);
//		Log.d(SysFunc.Log_Key, "pushGroupRecvNotifyStr isOk = " + isOk + " downloadQueue.size() = " + downloadQueue.size());
//	}
//
//
//	private void pushGroupRecvNotify()
//	{
//		List<UserInfo>  userList = getGroupList();
//		if(userList != null
//				&& userList.size() > 0)
//		{
//			for(Iterator<UserInfo> iter = userList.iterator();iter.hasNext();)
//			{
//				UserInfo userInfo = iter.next();
//				Log.d(SysFunc.Log_Key, "pushGroupRecvNotify userInfo = " + userInfo);
//				String groupId = userInfo.getMcpttId();
//				pushGroupRecvNotifyStr(UserInfo.McType_Ptt,groupId);
//
//				groupId = userInfo.getMcvideoId();
//				pushGroupRecvNotifyStr(UserInfo.McType_Video,groupId);
//
//				groupId = userInfo.getMcdataId();
//				pushGroupRecvNotifyStr(UserInfo.McType_Data,groupId);
//			}
//		}
//	}
}
